
import {
    _decorator, Component, Input, instantiate, Node, Prefab, tween, Vec3,
    Label, sys, Widget, UITransform, director, SpriteFrame, resources, SpriteAtlas
} from 'cc';
import { Card } from './Card';
import { Config } from './Config';
import { utils } from './utils';



import { msgToast } from './msgToast';
import { msgGameWin } from './msgGameWin';
import { msgGameFail } from './msgGameFail';
import { msgGameRebirth } from './msgGameRebirth';
import { msgShare } from './msgShare';
import { AudioManager } from './AudioManager';
import { Btn } from './Btn';
import { SDKManager } from './SDKManager';


const { ccclass, property } = _decorator;

@ccclass('gameManager')
export class gameManager extends Component {


    @property(AudioManager)
    audioManager: AudioManager = null!;

    //游戏弹窗
    @property({ type: msgGameWin })
    public msgGameWin: msgGameWin = null!

    @property({ type: msgGameFail })
    public msgGameFail: msgGameFail = null!

    @property({ type: msgGameRebirth })
    public msgGameRebirth: msgGameRebirth = null!

    @property({ type: msgShare })
    public msgShare: msgShare = null!

    @property({ type: Node })
    public uiBackground: Node = null!;

    // 容器
    @property({ type: Node })
    public container: Node = null!;

    //卡牌预制体
    @property({ type: Prefab })
    public cardPrefab: Prefab = null!;

    //粒子系统预制体
    @property({ type: Prefab })
    public particle2D: Prefab = null!;

    // 设置按钮
    @property({ type: Node })
    public setBtn: Node = null!;

    // 插槽Bar
    @property({ type: Node })
    public bar: Node = null!;

    //关卡提示
    @property({ type: Label })
    public mLevel: Label = null!

    // 设置按钮
    @property({ type: Node })
    public uiLoading: Node = null!;
    // btn
    @property({ type: Node })
    public btnRemove: Node = null!;

    @property({ type: Node })
    public btnWithdraw: Node = null!;

    @property({ type: Node })
    public btnShuffle: Node = null!;

    @property({ type: Node })
    public flowers: Node = null!;


    @property({
        type: [SpriteFrame],
        displayName: '图片数组'

    })
    public sp: SpriteFrame[] = [];

    //加载地图
    private map: any[] = []
    //卡牌数量
    //private cardSum: number = 0

    //当前游戏关卡
    private level: number = 1

    //卡槽
    private slot: any[] = []
    //卡槽位置
    private slotWorldPoint: any[] = []
    //container--Transform
    private cTransform = null;

    //是否复活过
    private isRebirth: boolean = false

    /**
     * 卡片排序位置变化
     * @getSiblingIndex 函数返回的是「当前节点在父节点的 _children 属性中的下标（位置）
     * @setSiblingIndex 函数则是设置「当前节点在父节点的 _children 属性中的下标（位置）
     */
    private zIdx: number = 0;

    private gameState = Config.GAME_STATE.READY

    //分享时间需要大于3秒
    private shereNow: number = 0

  

    /**
     * 遍历box是否相交
     */
    checkClickable() {
        for (let i: number = 0; i < this.map.length; i++) {
            let isOverlap: boolean = false;
            for (let j: number = i + 1; j < this.map.length; j++) {
                if (!isOverlap) {
                    isOverlap = utils.isBoxOverlap(this.map[i].x, this.map[i].y, this.map[j].x, this.map[j].y, Config.CARD_WIDTH, Config.CARD_HIGHT);
                }
            }
            //box相交开启蒙版-不可点击
            this.map[i].clickable = !isOverlap
        }
    }

    initGame(i: number) {
        let self = this;
        //游戏数据准备中
        self.gameState = Config.GAME_STATE.READY
        self.slot = []
        //销毁节点及节点引用
        self.container.destroyAllChildren()
        self.container.removeAllChildren()

        self.isRebirth = false
        //加载游戏-默认第一关
        self.mLevel.string = `${i}`

        if (i <= Config.MAX_LEVEL) {
            // this.showToast('单机版')
            self.map = JSON.parse(JSON.stringify(Config[`GAME_LEVEL${i}`]))
            console.log( Config[`GAME_LEVEL_SKIN${i}`])
            self.initMap(Config[`GAME_SUM_CARD${i}`], Config[`GAME_LEVEL_SKIN${i}`])

        } else {
            self.uiLoading.active = true;
            //读取关卡代码
            utils.call('get', {
                type: 'docDoc',
                collection: 'CMS_GameMap',
                Id: i,
                field: {
                    _id: false,
                    cType: true,
                    gameSumCard: true,
                    gameMap: true
                }
            }).then(res => {
                let resa: any = res;
                self.uiLoading.active = false;
                //self.showToast('联网版')
                let jsonStr: string = resa?.gameMap as string || ''
                self.map = jsonStr ? JSON.parse(jsonStr) : []
                let cardSum: number = resa?.gameSumCard as number || 18
                let cType: number = resa?.cType as number || 1
                self.initMap(cardSum, cType)
            }).catch((err) => {
                self.uiLoading.active = false;
                //self.showToast('联网失败 单机模式')
                self.map = JSON.parse(JSON.stringify(Config[`GAME_LEVEL${Config.MAX_LEVEL}`]))
                self.initMap(Config[`GAME_SUM_CARD${2}`], Config[`GAME_LEVEL_SKIN${Config.MAX_LEVEL}`])
            })
        }
    }
    initMap(cardSUM: number, cType: number) {
        let self = this;
        self.zIdx = self.map.length;
        let val: any[] = utils.getArrayVal(self.map.length, cardSUM);

        self.checkClickable();
        self.sp = []

        //加载卡牌图片
        let url = `card${cType}/card`;
        console.log(url)
        resources.load(url, SpriteAtlas, (err: any, atlas) => {
            if (err) {
                return console.error("SpriteAtlas load failed, err:" + err.message);
            }
            // console.log(atlas.getSpriteFrame(`c1`))
            for (let i = 0; i < Config.MAX_CARD; i++) {
                self.sp.push(atlas.getSpriteFrame(`c${i + 1}`));
            }
            //设置预制体
            self.map.forEach((item, idx) => {
                let card = instantiate(self.cardPrefab);
                let component = card.getComponent(Card);
                component.init(self.sp[val[idx]]);
                component.clickable = item.clickable;
                self.container.addChild(card)
                card.setPosition(item.x, item.y, 0);

                item.card = card;
                item.v = val[idx];
                card.on(Input.EventType.TOUCH_START, self.cardClick, self);
            })
            //初始化地图位置和缩放比例
            self.container.setPosition(-500, 0)
            self.container.setScale(2, 2, 2)
           let y_pos = self.container.parent.getChildByName('baikuang').position.y
            //地图加载动画
            tween(self.container).to(0.3, { position: new Vec3(0, y_pos), scale: (new Vec3(1, 1, 1)) })
                .call(() => {
                    self.gameState = Config.GAME_STATE.PLAYING
                }).start()
            //this.resetBtnData()
        });
    }

    start() {
        let self = this;
        //背景图片适配
        if (self.uiBackground) {
            self.uiBackground.setScale(1, Config.heightScaling)
        }

        //获取胶囊的rect
        let rect = SDKManager.getMenuButtonRect();
        if (rect) {
            let widget = self.setBtn.getComponent(Widget)
            widget.top = rect.top
        }
        let uiTransform = self.bar.getComponent(UITransform)
        //将距当前节点坐标系下的一个点转换到世界坐标系。
        let worldPoint = uiTransform.convertToWorldSpaceAR(new Vec3(0,0))
        console.log('worldPoint---', worldPoint)

        //动态计算卡槽世界坐标位置
        let { x, y } = worldPoint
        x = x - Config.CARD_WIDTH * 3 - 1
        for (let i = 1; i <= 7; i++) { self.slotWorldPoint.push({ x: x * i, y }) }
        console.log('slotWorldPoint---', this.slotWorldPoint)
        self.cTransform = self.container.getComponent(UITransform)

        self.initGame(this.level);


        tween(this.flowers)
        .to(0.5, { angle: 18 }, { easing: 'sineOut' })
        .to(0.5, { angle: -18 },{ easing:'quadIn' })
          .union()
          .repeatForever()
          .start()
    }



    //update(deltaTime: number) { }

    cardClick(e) {
        //判断卡槽是否已满，已满点击无效
        if (this.slot.length >= this.slotWorldPoint.length) return;

        let node = e.currentTarget
        let card = node.getComponent(Card)

        //console.log(`card-----id:${card.node._id}, val:${card.val}, x:${node.position.x}, y:${node.position.y}`)
        //card不可点击退出
        if (!card.clickable) return;
        //通过id比对，可以避免两张卡牌位置相同，之前通过位置比对，存在一个bug
        let id = card.node._id
        //let curPosition = { x: node.position.x, y: node.position.y }
        let mapIdx = this.map.findIndex(e => {
            return e.card._id === id
            //return e.x === curPosition.x && e.y === curPosition.y
        })

        if (-1 === mapIdx) return;

        let c = this.map[mapIdx]
        let cIdx: number = utils.getLastIndex(this.slot, c)

        this.audioManager.playSound()
        //放大效果
        node.scale = (new Vec3(1.5, 1.5, 0))
        //排序位置到最前面
        node.setSiblingIndex(this.zIdx)
        this.zIdx++;
        //关闭按钮事件
        node.off(Input.EventType.TOUCH_START, this.cardClick, this)
        //卡槽添加卡牌对象
        cIdx === -1 ? this.slot.push(this.map[mapIdx]) : this.slot.splice(cIdx + 1, 0, this.map[mapIdx])
        //map删除卡牌对象
        this.map.splice(mapIdx, 1)

        // 卡槽插入的卡牌后面的牌后移位置
        for (let i: number = this.slot.length - 1; i > cIdx; i--) {
            let node = this.slot[i].card
            //卡片后移动作
            tween(node).to(0.2, { scale: new Vec3(0.85, 0.85, 0.85), position: this.cTransform.convertToNodeSpaceAR(new Vec3(this.slotWorldPoint[i].x, this.slotWorldPoint[i].y)) })
                .call(() => {
                    this.checkClickable()
                    this.map.forEach(item => {
                        item.card.getComponent(Card).clickable = item.clickable
                    })
                }).start()
        }

        //判断是否有三个相同的卡片
        let sum = cIdx === -1 ? this.slot.length - 1 : cIdx + 1
        if ((sum > 1) && (this.slot[sum].v == this.slot[sum - 1].v) && (this.slot[sum].v == this.slot[sum - 2].v)) {
            //有三张相同的牌--卡牌消失，播放粒子效果
            for (let i: number = sum; i > sum - 3; i--) {
                let node = this.slot[i].card
                tween(node).delay(0.3).to(0.2, { scale: new Vec3(0, 0, 0), position: this.cTransform.convertToNodeSpaceAR(new Vec3(this.slotWorldPoint[i].x, this.slotWorldPoint[i].y)) })
                    .call(() => {
                        node.destroy();//直接销毁节点，最具有效率的方式
                        node.removeFromParent();//移除与父节点的引用

                        this.audioManager.playSound('eliminate')

                        let particle2D = instantiate(this.particle2D)
                        this.container.addChild(particle2D)
                        particle2D.setPosition(this.cTransform.convertToNodeSpaceAR(new Vec3(this.slotWorldPoint[i].x, this.slotWorldPoint[i].y)))

                    }).start()
            }

            //删除三张相同的卡牌，其后的卡牌前移
            this.slot.splice(sum - 2, 3)
            for (let j: number = sum - 2; j < this.slot.length; j++) {
                let node = this.slot[j].card
                //卡片前移一位
                tween(node).delay(0.5)
                    .to(0.2, { scale: new Vec3(0.85, 0.85, 0.85), position: this.cTransform.convertToNodeSpaceAR(new Vec3(this.slotWorldPoint[j].x, this.slotWorldPoint[j].y)) })
                    .start()
            }
            if (this.map.length <= 0) {

                this.gameState = Config.GAME_STATE.PAUSE
                this.showToast('闯关成功')
                this.audioManager.playSound('win')
                this.msgGameWin.show(this.level)
            }

        } else {
            if (this.slot.length >= this.slotWorldPoint.length) {
                this.gameState = Config.GAME_STATE.OVER
                this.audioManager.playSound('over')
                this.showToast('闯关失败')
                //未使用玩移除道具次数,道具次数
                this.isRebirth ? this.msgGameFail.show(this.level) : this.msgGameRebirth.show()

            }

        }

    }

    //工具奖励能力
    onCallBackBtn(e, d) {
        this.msgShare.hide()
        let { idx, mode } = JSON.parse(d)
        0 === mode ? this.shereApp(idx) : this.play(idx)
    }

    shereApp(idx: number) {
        let self = this;
        let node = 0 === idx ? this.btnRemove : 1 === idx ? this.btnWithdraw : this.btnShuffle
        let btn = node.getComponent(Btn);

        SDKManager.shareAppMessage(data => {
            if (1 === data) {
                {
                    //克隆节点
                    let icon: Node = node.getChildByName('icon');
                    let s = instantiate(icon);

                    //设置父节点
                    s.parent = node
                    let localPos = node.inverseTransformPoint(icon.getPosition(), new Vec3(360, 700, 0))
                    s.setPosition(localPos)

                    let t1 = tween(s).to(.2, { scale: new Vec3(1.6, 1.6) })
                    let t2 = tween(s).to(.2, { scale: new Vec3(1, 1) })
                    let t3 = tween(s).to(.5, { position: new Vec3(0, 0) })
                    let t4 = tween(s).to(.1, { scale: new Vec3(1.2, 1.2) })
                    let t5 = tween(s).to(.1, { scale: new Vec3(1, 1) })
                    tween(s).sequence(t1, t2, t3, t4, t5).call(() => {
                        s.destroy();//直接销毁节点，最具有效率的方式
                        s.removeFromParent();//移除与父节点的引用
                        if ((new Date().getTime() - self.shereNow < 1000 * 5) && (sys.platform === sys.Platform.WECHAT_GAME)) {
                            self.showToast('请分享更多群')
                            return;
                        } else {
                            self.showToast('获得一个道具奖励')
                            btn.setCanUse(btn.getCanUse() + 1)
                            btn.setMaxUse(btn.getMaxUse() - 1)
                        }

                    }).start()
                }
            } else {
                this.showToast('未成功分享')
            }
        })

    }
    play(idx: number) {
        let self = this;
        let node = 0 === idx ? this.btnRemove : 1 === idx ? this.btnWithdraw : this.btnShuffle;
        let btn = node.getComponent(Btn)
        SDKManager.showRewardedVideoAd(data => {
            if (0 === data) {
                self.showToast('视频播放未完成')
            } else if (1 === data) {
                {
                    //克隆节点
                    //console.log('-----', btn.getMaxUse() < 1)
                    let icon: Node = node.getChildByName('icon');
                    let s = instantiate(icon);

                    //设置父节点
                    s.parent = node
                    let localPos = node.inverseTransformPoint(icon.getPosition(), new Vec3(360, 700, 0))
                    s.setPosition(localPos)

                    let t1 = tween(s).to(.2, { scale: new Vec3(1.6, 1.6) })
                    let t2 = tween(s).to(.2, { scale: new Vec3(1, 1) })
                    let t3 = tween(s).to(.5, { position: new Vec3(0, 0) })
                    let t4 = tween(s).to(.1, { scale: new Vec3(1.2, 1.2) })
                    let t5 = tween(s).to(.1, { scale: new Vec3(1, 1) })
                    tween(s).sequence(t1, t2, t3, t4, t5).call(() => {
                        s.destroy();//直接销毁节点，最具有效率的方式
                        s.removeFromParent();//移除与父节点的引用

                        self.showToast('获得移除道具')
                        btn.setCanUse(btn.getCanUse() + 1)
                        btn.setMaxUse(btn.getMaxUse() - 1)
                        // btn.setCanUse(1)
                        // btn.setMaxUse(0)
                    }).start()
                }
            } else {
                self.showToast('播放加载失败')
            }

        })
    }

    //游戏结束时的奖励确认
    onBtnConfirm() {
        let self = this;

        SDKManager.showRewardedVideoAd(data => {
            if (0 === data) {
                self.showToast('视频播放未完成')
            } else if (1 === data) {
                {
                    self.isRebirth = true
                    self.msgGameRebirth.hide()
                    self.gameState = Config.GAME_STATE.PLAYING
                    let len: number = self.slot.length
                    let mlen: number = len > 3 ? 3 : len
                    //卡槽移除卡牌
                    for (let i = 0; i < len; i++) {
                        let n = self.slot[i].card
                        if (i < mlen) {
                            //卡牌位置重新赋值--刚刚播放的在右边
                            let nodePoint = self.cTransform.convertToNodeSpaceAR(new Vec3(self.slotWorldPoint[i + 4].x, self.slotWorldPoint[i].y + 150))
                            self.slot[i].x = nodePoint.x
                            self.slot[i].y = nodePoint.y
                            tween(n).to(0.2, { position: nodePoint }).call(() => {
                                //绑定按钮事件
                                n.on(Input.EventType.TOUCH_START, self.cardClick, self)
                            }).start()
                        } else {
                            tween(n).to(0.2, { position: self.cTransform.convertToNodeSpaceAR(new Vec3(self.slotWorldPoint[i - 3].x, self.slotWorldPoint[i - 3].y)) }).start()
                        }
                    }
                    let c = self.slot.splice(0, mlen)
                    self.map.push(...c)
                }
            } else {
                self.showToast('视频播放失败')
            }

        })
    }



    //游戏结束时的奖励取消
    onBtnCancel() {
        this.msgGameRebirth.hide()
        this.msgGameFail.show(this.level)
    }
    onDirectorMain() {
        director.loadScene('gameMain');
    }

    onRestart() {
        this.msgGameFail.hide()
        this.initGame(this.level)
        this.resetBtnData()
    }
    onNextGame() {
        this.msgGameWin.hide()
        this.level += 1
        this.initGame(this.level)
        this.resetBtnData()
    }
    //按钮数据重置
    resetBtnData() {
        let btn1 = this.btnRemove.getComponent(Btn)
        btn1.getCanUse() > 0 ? btn1.setMaxUse(0) : btn1.setMaxUse(1)

        let btn2 = this.btnWithdraw.getComponent(Btn)
        btn2.getCanUse() > 0 ? btn2.setMaxUse(0) : btn2.setMaxUse(1)

        let btn3 = this.btnShuffle.getComponent(Btn)
        btn3.getCanUse() > 0 ? btn3.setMaxUse(0) : btn3.setMaxUse(1)

    }
    //功能-移除3个卡牌
    onRemove(e) {
        let self = this;
        self.audioManager.playSound()

        if (self.gameState != Config.GAME_STATE.PLAYING) {
            self.showToast('请稍后')
        }
        let node = e.currentTarget
        let btn = node.getComponent(Btn)
        let state = btn.getBtnState()
        console.log('-----', state)
        if (0 === state) {
            let len: number = self.slot.length
            if (0 === len) {
                self.showToast('没有可以移除的卡牌')
                return;
            } else {
                btn.setCanUse(btn.getCanUse() - 1)
                let mlen: number = len > 3 ? 3 : len
                //卡槽移除卡牌
                for (let i = 0; i < len; i++) {
                    let n = self.slot[i].card
                    if (i < mlen) {
                        //卡牌位置重新赋值
                        let nodePoint = self.cTransform.convertToNodeSpaceAR(new Vec3(self.slotWorldPoint[i].x, self.slotWorldPoint[i].y + 150))
                        self.slot[i].x = nodePoint.x
                        self.slot[i].y = nodePoint.y
                        tween(n).to(0.2, { position: nodePoint }).call(() => {
                            //绑定按钮事件
                            n.on(Input.EventType.TOUCH_START, self.cardClick, self)
                        }).start()
                    } else {
                        tween(n)
                            .to(0.2, { position: self.cTransform.convertToNodeSpaceAR(new Vec3(self.slotWorldPoint[i - 3].x, self.slotWorldPoint[i - 3].y)) }).start()
                    }
                }
                let c = self.slot.splice(0, mlen)
                self.map.push(...c)
            }

        } else if (1 == state) {
            //self.msgShare.init(0, Math.round(Math.random()))
            self.msgShare.init(0, 1)//移除功能只允许视频观看奖励
            self.msgShare.show()
        } else {
            self.audioManager.playSound()
            self.showToast('每关仅能使用1次移除道具')
        }

    }
    //功能-撤销
    onWithdraw(e) {
        let self = this;
        self.audioManager.playSound()
        if (self.gameState != Config.GAME_STATE.PLAYING) {
            self.showToast('请稍后')
        }
        let node = e.currentTarget
        let btn = node.getComponent(Btn)
        let state = btn.getBtnState()
        if (0 === state) {
            let len: number = self.slot.length
            if (0 === len) {
                self.showToast('没有可以撤销的卡牌')
                return;
            } else {
                btn.setCanUse(btn.getCanUse() - 1)
                let n = self.slot[len - 1].card
                tween(n).to(0.2, { position: new Vec3(self.slot[len - 1].x, self.slot[len - 1].y) }).call(() => {
                    //绑定按钮事件
                    n.on(Input.EventType.TOUCH_START, self.cardClick, self)
                    let c = self.slot.splice(len - 1, 1)
                    self.map.push(...c)
                }).start()
            }
        } else if (1 == state) {
            this.shereNow = new Date().getTime()
            self.msgShare.init(1, Math.round(Math.random()))
            self.msgShare.show()
        } else {
            self.audioManager.playSound()
            self.showToast('每关仅能使用1次撤销道具')
        }

    }

    //功能-洗牌
    onShuffle(e) {
        let self = this;
        self.audioManager.playSound()
        if (self.gameState != Config.GAME_STATE.PLAYING) {
            self.showToast('请稍后')
        }
        let node = e.currentTarget
        let btn = node.getComponent(Btn)
        let state = btn.getBtnState()
        if (0 === state) {
            let len: number = self.map.length;
            if (0 === len) {
                self.showToast('没有可以洗牌的卡牌')
                return;
            } else {
                btn.setCanUse(btn.getCanUse() - 1)
                //生产数组
                let selfArray: number[] = []
                let selfArrayV: number[] = []
                self.map.forEach((item, index) => {
                    selfArray.push(index)
                    selfArrayV.push(item.v)
                })
                let shuffledArray: number[] = utils.getShuffledArray(selfArray);
                for (let i = 0; i < len; i++) {
                    let n = self.map[i].card;
                    //产生随机洗牌效果
                    let ran: number = shuffledArray[i];
                    tween().target(n).to(.5, { position: new Vec3(self.map[ran].x, self.map[ran].y) }).call(() => {
                        let component = n.getComponent(Card)
                        component.init(self.sp[selfArrayV[ran]]);
                        self.map[i].v = selfArrayV[ran]
                    }).to(.5, { position: new Vec3(self.map[i].x, self.map[i].y) }).start()
                }
            }
        } else if (1 == state) {
            this.shereNow = new Date().getTime()
            self.msgShare.init(2, Math.round(Math.random()))
            self.msgShare.show()
        } else {
            self.audioManager.playSound()
            self.showToast('每关仅能使用1次洗牌道具')
        }

    }


    //showToast
    @property({ type: Prefab })
    public toastPrefab: Prefab = null!;
    /**
     * showToast
     * @param conent 内容
     */
    public showToast(conent: string) {
        let t = instantiate(this.toastPrefab)
        let script = t.getComponent(msgToast);
        script.showToast(conent)
        this.node.addChild(t)
    }

}

